/*******************************************************************************
 * file  : des demo
 * creat : apleilx
 * data  : 2017/03/02
 *******************************************************************************/
#include "framework.h"
#include "str_ext.h"

/*******************************************************************************
 * @brief  micro
 *******************************************************************************/
#define DISP_MODE_HEX 0	 // 16进制显示
#define DISP_MODE_IDEC 1 // 10进制显示-有符号
#define DISP_MODE_UDEC 2 // 10进制显示-无符号
#define DISP_MODE_BIN 3	 // 2进制显示
#define DISP_MODE_FLT 4	 // 2进制显示

/*******************************************************************************
 * @brief  function
 *******************************************************************************/
char mem_head_disp(const void *head);
void assert_message_output(const char *file, int line, const char *message);
void assert_value_msg_output(const char *file, int line, int value, const char *message);

/*******************************************************************************
 * @brief  8位格式显示内存信息
 * \param[in] head :添加信息头
 * \retval: data mode
 *******************************************************************************/
char mem_head_disp(const void *head)
{
	char mode = DISP_MODE_HEX;

	// 输出头
	if (head)
	{
		ii8 head_site;
		const char *hd = head;

		// 模式选择
		if (hd[0] == 'I' && hd[1] == ':')
		{
			mode = DISP_MODE_IDEC;
			head_site = 1;
		}
		else if (hd[0] == 'U' && hd[1] == ':')
		{
			mode = DISP_MODE_UDEC;
			head_site = 1;
		}
		else if (hd[0] == 'B' && hd[1] == ':')
		{
			mode = DISP_MODE_BIN;
			head_site = 1;
		}
		else if (hd[0] == 'F' && hd[1] == ':')
		{
			mode = DISP_MODE_FLT;
			head_site = 1;
		}
		else
		{
			head_site = 0;
		}

		// 纯文本判定
		if (head_site > 0)
		{
			head_site++;
			if (!hd[head_site])
			{
				head_site = -1;
			}
		}

		// 打印头
		if (head_site >= 0)
		{
			com_print("%s", hd + head_site);
		}
	}

	return mode;
}

/*******************************************************************************
 * @brief  8位格式显示内存信息
 * \param[in] head :添加信息头
 * \param[in] dat  :数据地址
 * \param[in] len  :长度
 * \param[in] line :每行最大显示数量
 * \retval: none
 *******************************************************************************/
void mem_u8_disp(const void *head, const void *dat, int len, int line)
{
	const uu8 *ch = dat;
	const ii8 *ich = dat;
	const float *fch = dat;
	char mode;
	int cnt = 0;
	ii8 bit;

	(void)ch;
	(void)ich;

	mode = mem_head_disp(head);

	// 输出数据
	while (len--)
	{
		switch (mode)
		{
		case DISP_MODE_UDEC:
			com_print("%3d ", *ch++);
			break;
		case DISP_MODE_IDEC:
			com_print("%4d ", *ich++);
			break;
		case DISP_MODE_FLT:
			com_print("%12.2f ", *fch++);
			break;
		case DISP_MODE_BIN:
			for (bit = 7; bit >= 0; bit--)
			{
				if (*ch & (1U << bit))
					com_puts("1");
				else
					com_puts("0");
			}
			com_puts(" ");
			ch++;
			break;
		default:
			com_print("%02X ", *ch++);
			break;
		}

		cnt++;

		if ((cnt % line) == 0)
		{
			com_print(" =>line#%d\n", cnt / line);
		}
	}

	// 行尾添加换行符
	if ((cnt % line) != 0)
	{
		com_puts("\n");
	}
}

/*******************************************************************************
 * @brief  16位格式显示内存信息
 * \param[in] head :添加信息头
 * \param[in] dat  :数据地址
 * \param[in] len  :长度
 * \param[in] line :每行最大显示数量
 * \retval: none
 *******************************************************************************/
void mem_u16_disp(const void *head, const void *dat, int len, int line)
{
	const uu16 *ch = dat;
	const ii16 *ich = dat;
	const float *fch = dat;
	char mode;
	int cnt = 0;

	(void)ch;
	(void)ich;

	mode = mem_head_disp(head);

	// 输出数据
	while (len--)
	{
		switch (mode)
		{
		case DISP_MODE_UDEC:
			com_print("%5d ", *ch++);
			break;
		case DISP_MODE_IDEC:
			com_print("%6d ", *ich++);
			break;
		case DISP_MODE_FLT:
			com_print("%12.2f ", *fch++);
			break;
		default:
			com_print("%04X ", *ch++);
			break;
		}

		cnt++;

		if ((cnt % line) == 0)
		{
			com_print(" =>line#%d\n", cnt / line);
		}
	}

	// 行尾添加换行符
	if ((cnt % line) != 0)
	{
		com_puts("\n");
	}
}

/*******************************************************************************
 * @brief  32位格式显示内存信息
 * \param[in] head :添加信息头
 * \param[in] dat  :数据地址
 * \param[in] len  :长度
 * \param[in] line :每行最大显示数量
 * \retval: none
 *******************************************************************************/
void mem_u32_disp(const void *head, const void *dat, int len, int line)
{
	const uu32 *ch = dat;
	const ii32 *ich = dat;
	const float *fch = dat;

	char mode;
	int cnt = 0;

	(void)ch;
	(void)ich;

	mode = mem_head_disp(head);

	// 输出数据
	while (len--)
	{
		switch (mode)
		{
		case DISP_MODE_UDEC:
			com_print("%10d ", *ch++);
			break;
		case DISP_MODE_IDEC:
			com_print("%11d ", *ich++);
			break;
		case DISP_MODE_FLT:
			com_print("%12.2f ", *fch++);
			break;
		default:
			com_print("%08X ", *ch++);
			break;
		}

		cnt++;

		if ((cnt % line) == 0)
		{
			com_print(" =>line#%d\n", cnt / line);
		}
	}

	// 行尾添加换行符
	if ((cnt % line) != 0)
	{
		com_puts("\n");
	}
}

/*------------------------------------------------------------------------------
ANSI 标准 C 还定义了如下几个宏：
_LINE_ 表示正在编译的文件的行号
_FILE_ 表示正在编译的文件的名字,含路径
_DATE_ 表示编译时刻的日期字符串，例如： "25 Dec 2007"，__DATE__
_TIME_ 表示编译时刻的时间字符串，例如： "12:30:55", __TIME__
_STDC_ 判断该文件是不是定义成标准 C 程序
*-----------------------------------------------------------------------------*/
void assert_message_output(const char *file, int line, const char *message)
{
	int16_t site;

	// 文件名提取
	site = str_nsearch_ch(file, '\\');
	if (site < 0)
		site = str_nsearch_ch(file, '/');

	if (site >= 0)
		file = &file[site + 1];

	if (message)
	{
		dbg_print("TRACE:: %s @ FILE: %s => LINE : %d\n", message, file, line);
	}
	else
	{
		dbg_print("TRACE:: @ FILE: %s => LINE : %d\n", file, line);
	}
}

void assert_value_msg_output(const char *file, int line, int value, const char *message)
{
	int16_t site;

	// 文件名提取
	site = str_nsearch_ch(file, '\\');
	if (site < 0)
		site = str_nsearch_ch(file, '/');

	if (site >= 0)
		file = &file[site + 1];

	if (message)
	{
		dbg_print("TRACE:: %s, VALUE: %d @ FILE: %s => LINE : %d\n", message, value, file, line);
	}
	else
	{
		dbg_print("TRACE:: VALUE: %d @ FILE: %s => LINE : %d\n", value, file, line);
	}
}
